import { ref, watch, Ref, defineComponent, computed, onMounted } from 'vue';
import {
  getDataPickerProps,
  getEditorEmits,
  useNamespace,
} from '@ibiz-template/vue3-util';
import './ibiz-mpicker.scss';
import { clone } from 'lodash-es';
import { PickerEditorController } from '../picker-editor.controller';

export const IBizMPicker = defineComponent({
  name: 'IBizMPicker',
  props: getDataPickerProps<PickerEditorController>(),
  emits: getEditorEmits(),
  setup(props, { emit }) {
    const ns = useNamespace('mpicker');

    const c = props.controller!;

    // 当前表单项绑定值key的集合
    const curValue: Ref<Array<string>> = ref([]);

    // 实体数据集
    const items: Ref<IData[]> = ref([]);

    // 选中项key-value键值对
    const selectItems: Ref<IData[]> = ref([]);

    // 下拉是否打开
    const open = ref(false);

    // 加载中
    const loading: Ref<boolean> = ref(false);

    // 是否编辑态
    const isEditable = ref(false);

    // 编辑器Ref
    const editorRef = ref();

    // 是否显示表单默认内容
    const showFormDefaultContent = computed(() => {
      if (
        props.controlParams &&
        props.controlParams.editmode === 'hover' &&
        !props.readonly
      ) {
        return true;
      }
      return false;
    });

    // 监听传入值
    watch(
      () => props.value,
      newVal => {
        curValue.value = [];
        selectItems.value = [];
        if (newVal) {
          if (c.model.valueType === 'OBJECTS') {
            (newVal as Array<IData>).forEach((item: IData) => {
              const _item = clone(item);
              Object.assign(_item, {
                [c.keyName]: item[c.objectIdField as string],
                [c.textName]: item[c.objectNameField as string],
              });
              if (c.objectValueField) {
                Object.assign(_item, {
                  ...item[c.objectValueField],
                });
                delete _item[c.objectValueField];
              }
              if (_item[c.keyName]) {
                selectItems.value.push(_item);
              }
            });
          } else if (c.objectIdField && c.model.valueSeparator) {
            const values = (newVal as string).split(c.model.valueSeparator);
            values.forEach((value: string) => {
              selectItems.value.push({
                [c.keyName]: value,
              });
            });
          } else {
            try {
              selectItems.value = JSON.parse(newVal as string);
            } catch (error) {
              ibiz.log.error(
                `SIMPLE类型地址栏值格式${newVal}不符合JSON字符串要求`,
              );
            }
          }
          selectItems.value.forEach((item: IData) => {
            curValue.value.push(item[c.keyName]);
            // 选项没有的时候补充选项
            const index = items.value.findIndex(i =>
              Object.is(i[c.keyName], item[c.keyName]),
            );
            if (index < 0) {
              items.value.push({
                [c.keyName]: item[c.keyName],
                [c.textName]: item[c.textName],
              });
            }
          });
        }
      },
      { immediate: true, deep: true },
    );

    const setEditable = (flag: boolean) => {
      if (flag) {
        isEditable.value = flag;
      } else {
        setTimeout(() => {
          isEditable.value = flag;
        }, 100);
      }
    };

    // 处理视图关闭，往外抛值
    const handleOpenViewClose = (result: IData[]) => {
      // 抛出值集合
      const selects: IData[] = [];
      if (result && Array.isArray(result)) {
        result.forEach((select: IData) => {
          Object.assign(select, {
            [c.keyName]: select[c.keyName] ? select[c.keyName] : select.srfkey,
            [c.textName]: select[c.textName]
              ? select[c.textName]
              : select.srfmajortext,
          });
          if (c.model.valueType === 'OBJECTS') {
            selects.push(c.handleObjectParams(select));
          } else if (c.objectIdField) {
            selects.push(select[c.keyName]);
          } else {
            selects.push({
              [c.keyName]: select[c.keyName],
              [c.textName]: select[c.textName],
            });
          }
          const index = items.value.findIndex(item =>
            Object.is(item[c.keyName], select[c.keyName]),
          );
          if (index < 0) {
            items.value.push(select);
          }
        });
      }
      let value: string | Array<IData> | null = null;
      if (selects.length > 0) {
        if (c.model.valueType === 'OBJECTS') {
          value = selects;
        } else {
          value = c.objectIdField
            ? selects.join(c.model.valueSeparator)
            : JSON.stringify(selects);
        }
      }
      emit('change', value);
      setEditable(false);
    };

    // 打开数据选择视图
    const openPickUpView = async () => {
      let selectedData;
      if (selectItems.value.length) {
        const _selectItems = JSON.parse(JSON.stringify(selectItems.value));
        _selectItems.forEach((item: IData, index: number) => {
          _selectItems[index].srfkey = item[c.keyName];
          _selectItems[index].srfmajortext = item[c.textName];
        });
        selectedData = JSON.stringify(_selectItems);
      }
      const res = await c.openPickUpView(props.data!, selectedData);
      if (res) {
        handleOpenViewClose(res);
      }
    };

    // 下拉选中回调
    const onSelect = (selects: string[]) => {
      const val: Array<IData> = [];
      let value: string | Array<IData> | null = null;
      if (selects.length > 0) {
        selects.forEach((select: string) => {
          let index = items.value.findIndex(item =>
            Object.is(item[c.keyName], select),
          );
          let item: IData = {};
          if (index >= 0) {
            item = items.value[index];
          } else {
            index = selectItems.value.findIndex((selectItem: IData) =>
              Object.is(selectItem[c.keyName], select),
            );
            if (index >= 0) {
              item = selectItems.value[index];
            }
          }
          if (c.model.valueType === 'OBJECTS') {
            val.push(c.handleObjectParams(item));
          } else if (c.objectIdField) {
            val.push(item[c.keyName]);
          } else {
            val.push({
              [c.keyName]: item[c.keyName],
              [c.textName]: item[c.textName],
            });
          }
        });
        if (val.length > 0) {
          if (c.model.valueType === 'OBJECTS') {
            value = val;
          } else {
            value = c.objectIdField
              ? val.join(c.model.valueSeparator)
              : JSON.stringify(val);
          }
        }
        emit('change', value);
      }
      setEditable(false);
    };

    // 移除标签回调
    const onRemove = (tag: string) => {
      const index = selectItems.value.findIndex((item: IData) =>
        Object.is(item[c.keyName], tag),
      );
      if (index >= 0) {
        selectItems.value.splice(index, 1);
        const val: Array<IData> = [];
        let value: string | Array<IData> | null = null;
        selectItems.value.forEach((select: IData) => {
          if (c.model.valueType === 'OBJECTS') {
            val.push(c.handleObjectParams(select));
          } else if (c.objectIdField) {
            val.push(select[c.keyName]);
          } else {
            val.push({
              [c.keyName]: select[c.keyName],
              [c.textName]: select[c.textName],
            });
          }
        });
        if (val.length > 0) {
          if (c.model.valueType === 'OBJECTS') {
            value = val;
          } else {
            value = c.objectIdField
              ? val.join(c.model.valueSeparator)
              : JSON.stringify(val);
          }
        }
        emit('change', value);
      }
    };

    // 搜索
    const onSearch = async (query: string) => {
      if (c.model.appDataEntityId) {
        loading.value = true;
        try {
          const trimQuery = query.trim();
          const res = await c.getServiceData(trimQuery, props.data!);
          loading.value = false;
          if (res) {
            items.value = res.data as IData[];
          }
        } catch (error) {
          loading.value = false;
        }
      }
    };

    // 下拉打开
    const onOpenChange = (flag: boolean) => {
      open.value = flag;
      if (open.value) {
        items.value = [];
        onSearch('');
      }
    };

    // 信息展示，只显示名称。
    const valueText = computed(() => {
      return selectItems.value
        .map(item => {
          return item[c.textName];
        })
        .join(',');
    });

    watch(
      valueText,
      (newVal, oldVal) => {
        if (newVal !== oldVal) {
          emit('infoTextChange', newVal);
        }
      },
      { immediate: true },
    );

    // 聚焦
    const onFocus = (e: IData) => {
      emit('focus', e);
      setEditable(true);
    };

    // 失焦
    const onBlur = (e: IData) => {
      emit('blur', e);
      setEditable(false);
    };

    // 处理点击键盘
    const handleKeyUp = (e: KeyboardEvent) => {
      if (e && e.code === 'Enter') {
        emit('enter', e);
      }
    };

    onMounted(() => {
      if (c.objectNameField) {
        onSearch('');
      }
    });

    return {
      ns,
      c,
      curValue,
      loading,
      items,
      valueText,
      onSearch,
      onOpenChange,
      onSelect,
      onRemove,
      openPickUpView,
      onFocus,
      onBlur,
      handleKeyUp,
      selectItems,
      editorRef,
      isEditable,
      setEditable,
      showFormDefaultContent,
    };
  },
  render() {
    const overflowMode =
      this.c.editorParams.overflowMode || ibiz.config.pickerEditor.overflowMode;
    const isEllipsis = overflowMode === 'ellipsis';

    // 编辑态内容
    const editContent = [
      !this.readonly && (
        <el-select
          ref='editorRef'
          class={[this.ns.b('select')]}
          v-model={this.curValue}
          filterable
          remote
          multiple
          teleported={!this.showFormDefaultContent}
          loading={this.loading}
          placeholder={this.c.placeHolder ? this.c.placeHolder : ' '}
          remote-method={this.onSearch}
          onVisibleChange={this.onOpenChange}
          onChange={this.onSelect}
          onRemoveTag={this.onRemove}
          disabled={this.disabled}
          onFocus={this.onFocus}
          onBlur={this.onBlur}
          onKeyup={this.handleKeyUp}
          fit-input-width={isEllipsis}
          {...this.$attrs}
        >
          {this.items.map(item => {
            return (
              <el-option
                title={isEllipsis ? item[this.c.textName] : ''}
                key={item[this.c.keyName]}
                value={item[this.c.keyName]}
                label={item[this.c.textName]}
              ></el-option>
            );
          })}
        </el-select>
      ),
      !this.readonly && (
        <div class={this.ns.e('buns-position')}>
          <div class={this.ns.e('btns')}>
            {this.c.model.pickupAppViewId ? (
              <ion-icon onClick={this.openPickUpView} name='search'></ion-icon>
            ) : null}
          </div>
        </div>
      ),
    ];

    // 只读态内容
    const readonlyContent = (
      <div class={(this.ns.b(), this.ns.m('readonly'))}>{this.valueText}</div>
    );

    // 表单默认内容
    const formDefaultContent = (
      <div class={this.ns.b('form-default-content')}>
        {this.curValue.length > 0
          ? this.selectItems.map(item => {
              return (
                <span class={this.ns.b('content-item')}>
                  {item[this.c.textName]}
                </span>
              );
            })
          : '-'}
      </div>
    );

    return (
      <div
        class={[
          this.ns.b(),
          this.disabled ? this.ns.m('disabled') : '',
          this.readonly ? this.ns.m('readonly') : '',
          this.ns.is('editable', this.isEditable),
          this.ns.is('show-default', this.showFormDefaultContent),
        ]}
      >
        {this.showFormDefaultContent && formDefaultContent}
        {this.readonly ? readonlyContent : editContent}
      </div>
    );
  },
});
